// 函数参数的默认值

// // es5 写法
// function demo(x){
//     x = x || 'word';
//     console.log(x);
// }

// demo('hello');      //hello
// demo();             //word

// // es6
// function demo2(x='word'){
//     console.log(x);
// }

// demo2('123');       //123
// demo2();            //word

// // 注意事项1
// function demo3(x=1){
//     let x = 2;
//     console.log(x);
// }

// demo3();        // Errors while compiling. Reload prevented.

// 注意事项2
// console.log(function demo1(a){}.length)                 //1
// console.log(function demo2(a,b,c=0){}.length)           //2
// console.log(function demo3(a=0,b,v){}.length)           //0

// 注意事项3
// function demo(x=1,y) {
//     console.log(x+y)
// }
// demo(2,1)       //3
// demo(,2);       //Errors while compiling. Reload prevented.


//作用域
// let x = 1;
// function demo1(x,y=x){
//     console.log(y)
// }
// demo1();    //undefined

// function demo2(y=x){
//     let x = 2;
//     console.log(y)
// }
// demo2();    //1

// rest
// function add(...arr){
//     let t = 0;
//     for (let index = 0; index < arr.length; index++) {
//         t+=arr[index]
//     }
//     console.log(t)
// }

// add(1,2,3,4)        //10

// 注意1
// function test(...a,c){
//     console.log(a,c)
// }
// test(1,2,3)     //Errors while compiling. Reload prevented.

// 注意2
// console.log(function demo(a,...b){}.length)         //1

// name 属性
// let fo = function() {}
// console.log(fo.name)
//去掉babel转码否则报''  直接在浏览器里面操作

// 箭头函数
// 什么是箭头函数

// // 原来写法
// let test1 = function (){
//     return '1'
// }

// // 箭头函数
// let test2 = () => '2'

// console.log(test1(),test2())        //1 , 2 test1 和 test2 是等价的

// 什么时候使用括号与大括号

//括号 
// 在没有参数 或者 大于1个参数的时候必须使用括号
// 一个参数的时候可以用括号也可以不用 ps:使用默认值得时候除外必须使用括号

// let test3 = (a, b, c) => {
//     console.log(a, b, c)
// }
// let test4 = () => {
//     console.log(1)
// }
// let test5 = (a = 1) => {
//     console.log(a)
// }
// let test6 = a => {
//     console.log(a)
// }

// 大括号
// 什么时候可以不使用大括号
// 直接return 1 条语句的时候可以不使用其他的都要使用 ps：直接放回接送对象是另一种形式,加上括号
// 1 条语句的判断标准就是 是否觉得使用的分号 ';' 
// 如果 retun 的话 就使用 大括号

// let test7 = a => [1,2,3]
// let test8 = a => a + 1
// let test9 = (b=[],a=0) =>{
//     for (const i of b) {
//         a+=i
//     }
//     return a;
// }
// let test10 = ()=> ({a:1,b:0})

// console.log(test10())   //{a:1,b:0}

// 现在看了这么多了，应该对箭头函数比较了解了，来熟悉下
// 两个问题
// 1、写出判断是否是偶数的箭头函数
// 2、写出遍历一个数组后里面子集平方的箭头函数
// [1,2,3] =》 [1,4,9]

// // 第一题
// // 原来写法
// let isEven1 = function(n) {
//     return n % 2 === 0
// }
// // 箭头函数
// let isEven2 = n => n % 2 === 0;
// console.log(isEven1(1), isEven2(6))

// // 第二题
// 原来写法
// let square1 = function(arr = []) {
//     // let arr1 = [];
//     // for (const key in arr) {
//     //     // arr1.push(arr[key]*arr[key])
//     //     // 指数运算符
//     //     arr1.push(arr[key] ** 2)
//     // }
//     // return arr1;
//     return (arr.map(function(i) {
//         return i ** 2
//     }))
// }

// // es6 写法
// let square2 = (arr = []) => arr.map((i) => i ** 2);

// console.log(square1([2, 2, 3]), square2([2, 3, 4]))

// 箭头函数的 this
// const obj = {
//     id:100,
//     show(){
//         setTimeout(()=>{
//             console.log(this,this.id)   //100
//         },100);
//         setTimeout(function(){
//             console.log(this,this.id)   //undefined
//         },100);
//     }
// }
// obj.show();

// 不能使用new 箭头函数
// let foo1 = function(x) {
//     this.x = x;
//     this.show = function() {
//         console.log(this.x)
//     }
// }
// let foo2 = (x) => {
//     this.x = x;
//     this.show = () => {
//         console.log(this.x)
//     }
// }

// let Ofoo1 = new foo1('1');
// let Ofoo2 = new foo2('2');

// Ofoo1.show(); //1
// Ofoo2.show(); //show is not a function


// 箭头函数 没有 arguments
// let foo1 = function(...res){
//     console.log(arguments,res);
// }
// let foo2 = (...res)=>{
//     console.log(arguments,res);
// }

// foo1(1,2,3);
// foo2(1,2,3);


// 箭头函数不使用场合
// 第一个场合是定义函数的方法，且该方法内部包括this
// const obj = {
//     id:1,
//     init:()=>{
//         console.log(this);
//     },
//     show(){
//         console.log(this);
//     }
// }

// // 不能使用babel 编译 用浏览器打开
// obj.init();     //window
// obj.show();     //obj

// 第二个场合是需要动态this的时候，也不应使用箭头函数。
// 用浏览器才可以被打印出来
// // 创建按钮
// let p1 = document.createElement('p');
// let p2 = document.createElement('p');
// let p3 = document.createElement('p');
// p1.innerHTML = '按钮1';
// p2.innerHTML = '按钮2';
// p3.innerHTML = '按钮3';
// document.body.appendChild(p1);
// document.body.appendChild(p2);
// document.body.appendChild(p3);
// // 点击事件
// // this 指向全局
// p1.addEventListener("click",()=>{
//     console.log('按钮1 被点击了',this);
//     this.classList.toggle('on');
// });
// // 指向p
// p2.addEventListener("click",function(){
//     console.log('按钮2 被打了',this);
//     this.classList.toggle('on');
// });

// p3.onclick = ()=>{
//     // 指向window
//     console.log(this)
// }


// // 尾调用
// function f() {
//     return g(1)
// }

// // 这些是尾调用吗？
// // 情况一
// function f(x) {
//     let y = g(x);
//     return y;
// }

// // 情况二
// function f(x) {
//     return g(x) + 1;
// }

// // 情况三
// function f(x) {
//     g(x);
// }

// 递归 阶乘
// // 如果 1*2*3*4*5*6*7*8*9 用函数怎么写
// function f(a) {
//     if (a === 1) {
//         return a
//     }
//     return a * f(a - 1)
// }
// console.log(f(9)); //362880

// // 尾递归优化怎么写

// function fn(a, b = 1) {
//     if (a === 1) {
//         return b
//     }
//     return fn(a - 1, a * b);
// }
// console.log(fn(9)); //362880